package com.ddpt.permission.service.login;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.lh.center.activity.api.dubbo.ActivityDubboService;
import com.lh.center.activity.api.entity.ActivityInfoEntity;
import com.lh.center.common.constant.RedisPrefix;
import com.lh.center.common.dto.LoginByPhoneDto;
import com.lh.center.common.exception.CommonException;
import com.lh.center.common.exception.ErrorEnum;
import com.lh.center.common.util.AssertUtil;
import com.lh.center.common.util.IdUtil;
import com.lh.center.common.web.session.SessionOperation;
import com.lh.center.mall.api.dubbo.DubboMallService;
import com.lh.center.mall.api.entity.MallApplicationEntity;
import com.lh.center.merchant.api.dubbo.DubboMerchantInsService;
import com.lh.center.merchant.api.dubbo.DubboMerchantService;
import com.lh.center.merchant.api.dubbo.DubboPageService;
import com.lh.center.merchant.api.entity.Merchant;
import com.lh.center.merchant.api.entity.MerchantIns;
import com.lh.center.permission.api.session.UserSessionUser;
import com.lh.center.permission.service.LoginService;
import com.lh.center.permission.util.GtHttpUtil;
import com.lh.center.user.api.dubbo.DubboUserService;
import com.lh.center.user.api.entity.PsbcUserInfoExtEntity;
import com.lh.center.user.api.entity.UserEntity;
import com.lh.center.user.api.entity.UserGtXbExtEntity;
import com.lh.center.user.api.entity.WechatUserInfoExtEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service("userLoginService")
public class UserLoginServiceImpl implements LoginService<UserSessionUser> {

    @DubboReference
    private DubboPageService dubboPageService;

    @DubboReference
    private DubboMallService dubboMallService;

    @DubboReference
    private ActivityDubboService activityDubboService;


    @DubboReference
    private DubboUserService dubboUserService;

    @DubboReference
    private DubboMerchantService dubboMerchantService;

    @DubboReference
    private DubboMerchantInsService dubboMerchantInsService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private GtHttpUtil gtHttpUtil;

    @Override
    public UserSessionUser loginByPassword(String account, String password, String imgCode, String codeId) {
        return null;
    }

    @Override
    public UserSessionUser loginByPassword(String account, String password) {
        return null;
    }

    @Override
    public UserSessionUser loginByPhone(LoginByPhoneDto dto) {

        Long merchantId = null;
        Long insId = null;
        if (StringUtils.isNotBlank(dto.getActCode())){
            ActivityInfoEntity activityInfo = activityDubboService.getByCode(dto.getActCode());
            AssertUtil.isNull(activityInfo,"未知活动");
            merchantId = activityInfo.getMerchantId();
            insId = activityInfo.getInsId();
        }
        if (StringUtils.isNotBlank(dto.getMallCode())){

            MallApplicationEntity mallApplicationEntity = dubboMallService.getByCode(dto.getMallCode());
            AssertUtil.isNull(mallApplicationEntity,"未知商城");
            merchantId = mallApplicationEntity.getMerchantId();
            insId = mallApplicationEntity.getInsId();
        }
        if (StringUtils.isBlank(dto.getActCode()) && StringUtils.isBlank(dto.getMallCode())){
            Merchant merchant = dubboMerchantService.getByMerchantCode(dto.getMerchantCode());
            if (merchant == null){
                throw new CommonException("无此商户");
            }
            merchantId = merchant.getId();
            MerchantIns merchantIns = dubboMerchantInsService.getMerchantTopMerchantInsByMerchantId(merchantId);
            insId = merchantIns.getId();
        }

        String phone = dto.getPhone();
        String code = dto.getCode();

        AssertUtil.isTrue(StringUtils.isBlank(dto.getPhone()),"未知手机号码");
        AssertUtil.isTrue(StringUtils.isBlank(dto.getCode()),"验证码缺失");
        String phoneCode = stringRedisTemplate.opsForValue().get(RedisPrefix.PHONE_CODE + phone);

        AssertUtil.isTrue(StringUtils.isBlank(phoneCode),"验证码已失效");
        AssertUtil.isTrue(!code.equals(phoneCode),"验证码错误");


        // 补充手机号
        replenishPhone(dto, merchantId);

        UserEntity user = dubboUserService.registerOrGetUserByPhone(merchantId, insId, phone);
        if(user.isNewRegister() && StringUtils.isBlank(user.getUnionId())){
            user.setUnionId(phone);
            dubboUserService.fillUnionId(user.getId(),user.getUnionId());
        }
        stringRedisTemplate.delete(RedisPrefix.PHONE_CODE + phone);
        return loginSuccess(user);
    }

    @Override
    public void signOut(String token) {

    }

    @Override
    public UserSessionUser autoLogin(Long merchantId, String phone, String randomSecret) {
        // 自动登陆的时候 notes 2022-08-22
        UserEntity user = dubboUserService.registerOrGetUserByPhone(merchantId, null, phone);
        if(user == null){
            throw new CommonException("用户不存在");
        }
        if(StringUtils.isBlank(user.getRandomSecret()) || !user.getRandomSecret().equals(randomSecret)){
            throw new CommonException(ErrorEnum.user_not_login);
        }
        return loginSuccess(user);
    }


    public UserSessionUser loginSuccess(UserEntity user){
        // 并不会走我们的登录
//        dubboMemberOutSideService.updateOutSideMember(UserMemberQueryDto.builder()
//                .merchantId(user.getMerchantId())
//                .gradleId(user.getGradleId())
//                .getGradleLastTime(user.getGetGradleLastTime())
//                .unionId(user.getUnionId())
//                .build());
        UserSessionUser sessionUser = new UserSessionUser();
        //生成随机密码，并覆盖之前的
        user.setRandomSecret(UUID.randomUUID().toString().replace("-",""));
        String clientIP = ServletUtil.getClientIP(SessionOperation.getRequest());
        dubboUserService.updateLastRequest(user.getId(),user.getRandomSecret(),clientIP);
        // set 基础信息 start
        // 登录时，更新一下会员信息、登陆后用户会员变更，如青铜升白银，则需要用户点击查询最新会员信息。
        dubboUserService.userMemberQueryAndUpd(user.getId(), user, null);
        sessionUser.setGradleId(user.getGradleId());
        sessionUser.setUnionId(user.getUnionId());
        sessionUser.setAccount(user.getUnionId());
        sessionUser.setPhone(user.getPhone());
        sessionUser.setNickName(user.getNickName());
        sessionUser.setRealName(user.getRealName());
        sessionUser.setHeaderImg(user.getHeaderImg());
        sessionUser.setRandomSecret(user.getRandomSecret());
        sessionUser.setNewRegister(user.isNewRegister());
        // set 基础信息 end
        sessionUser.setUserId(user.getId());
        // notes 用户的机构id和瑞丰的机构id区分开 瑞丰用insIdStr字段。
        sessionUser.setInsId(user.getInsId());
        sessionUser.setMerchantId(user.getMerchantId());
        Merchant merchant = dubboMerchantService.getById(user.getMerchantId());
        sessionUser.setMerchantName(merchant.getName());
        String token = UUID.randomUUID().toString().replace("-","");
        sessionUser.setToken(token);
        //是否开启加解密
        if(SessionOperation.getConfiguration().isEnableSecret()){
            sessionUser.setSecret(RandomUtil.randomString(16));
            sessionUser.setSecretEnabled(true);
        }
        stringRedisTemplate.opsForValue().set(RedisPrefix.USER_ADMIN_USER_TOKEN+token, JSONUtil.toJsonStr(sessionUser),30, TimeUnit.MINUTES);
        return sessionUser;
    }





    private void replenishPhone(LoginByPhoneDto dto, Long merchantId) {
        String phone = dto.getPhone();
        if (StringUtils.isNotBlank(dto.getAuthKey())) {
            log.info("开始进入补充用户手机号逻辑:{}", dto.getAuthKey());
            Assert.notNull(dto.getAuthType());
            if (StringUtils.equals(dto.getAuthType(), "wechat_platform")) {
                String authKey = dto.getAuthKey();
                String wxInfo = dubboUserService.getAuthId(RedisPrefix.KEY_WECHAT_PLATFORM_AUTH_ID+authKey);
                if (StringUtils.isBlank(wxInfo)) {
                    throw new CommonException("登录失效,请从入口重新进入");
                }
                String[] wxInfoArr = wxInfo.split(":");
                String openId = wxInfoArr[0];
                String appId = wxInfoArr[1];


                WechatUserInfoExtEntity wechatUserInfoExtEntityFind = dubboUserService.getUserWechatExtByAppIdAndOpenId(null, appId,  openId);
                if (wechatUserInfoExtEntityFind != null) {
                    UserEntity user = dubboUserService.getById(wechatUserInfoExtEntityFind.getUserId());
                    if (user == null) {
                        throw new CommonException("用户信息不存在");
                    }

                    if (StringUtils.isBlank(user.getPhone())){
                        user.setPhone(dto.getPhone());
                        dubboUserService.updateBaseInfo(user);
                    }

                } else {
                    log.info("手机号登录判断邮储用户信息为空");
                    UserEntity user = dubboUserService.getByPhone(phone, merchantId);
                    if (user == null ) {
                        log.info("手机号登录判断邮储用户未曾客群创建用户,进入新增user流程");
                        UserEntity userDto = new UserEntity();
                        userDto.setId(IdUtil.nextId());
                        userDto.setUnionId(openId);
                        userDto.setMerchantId(merchantId);
                        userDto.setPhone(phone);

                        user = dubboUserService.saveUser(userDto);
                        WechatUserInfoExtEntity wechatUserInfoExtEntity = new WechatUserInfoExtEntity();
                        wechatUserInfoExtEntity.setOpenId(openId);
                        wechatUserInfoExtEntity.setAppId(appId);
                        wechatUserInfoExtEntity.setMerchantId(merchantId);
                        wechatUserInfoExtEntity.setUserId(user.getId());
                        dubboUserService.saveUserWechatExt(wechatUserInfoExtEntity);
                    } else {
                        log.info("手机号登录判断邮储用户客群已创建用户,进入补充邮储客户信息流程");


                        WechatUserInfoExtEntity wechatUserInfoExtEntity = new WechatUserInfoExtEntity();
                        wechatUserInfoExtEntity.setOpenId(openId);
                        wechatUserInfoExtEntity.setAppId(appId);
                        wechatUserInfoExtEntity.setMerchantId(merchantId);
                        wechatUserInfoExtEntity.setUserId(user.getId());
                        dubboUserService.saveUserWechatExt(wechatUserInfoExtEntity);
                    }
                }
            } else if("psbc_freeLogin".equals(dto.getAuthType())){
                String authKey = dto.getAuthKey();
                String authId = dubboUserService.getAuthIdByAuthKey(authKey);
                if (StringUtils.isBlank(authId)) {
                    throw new CommonException("登录失效,请从入口重新进入");
                }
                PsbcUserInfoExtEntity psbcUserInfoExtEntityFind = dubboUserService.getByPsbcUserId(authId, merchantId);
                if (psbcUserInfoExtEntityFind != null) {
                    UserEntity user = dubboUserService.getById(psbcUserInfoExtEntityFind.getUserId());
                    if (user == null) {
                        throw new CommonException("用户信息不存在");
                    }
                } else {
                    log.info("手机号登录判断邮储用户信息为空");
                    UserEntity user = dubboUserService.getByPhone(phone, merchantId);
                    if (user == null ) {
                        log.info("手机号登录判断邮储用户未曾客群创建用户,进入新增user流程");

                        UserEntity userDto = new UserEntity();
                        userDto.setUnionId(phone);
                        userDto.setLastIp(dto.getIp());
                        userDto.setMerchantId(merchantId);
                        userDto.setPhone(phone);

                        user = dubboUserService.registerUser(userDto);


                        PsbcUserInfoExtEntity psbcUserInfoExtEntity = new PsbcUserInfoExtEntity();
                        psbcUserInfoExtEntity.setPsbcUserId(authId);
                        psbcUserInfoExtEntity.setMerchantId(merchantId);
                        psbcUserInfoExtEntity.setUserId(user.getId());

                        dubboUserService.savePsbcUserInfoExt(psbcUserInfoExtEntity);

                    } else {
                        log.info("手机号登录判断邮储用户客群已创建用户,进入补充邮储客户信息流程");

                        PsbcUserInfoExtEntity psbcUserInfoExtEntity = new PsbcUserInfoExtEntity();
                        psbcUserInfoExtEntity.setPsbcUserId(authId);
                        psbcUserInfoExtEntity.setMerchantId(merchantId);
                        psbcUserInfoExtEntity.setUserId(user.getId());

                        dubboUserService.savePsbcUserInfoExt(psbcUserInfoExtEntity);



                    }


                }
            } else if("gtxb_freeLogin".equals(dto.getAuthType())) {
                String authKey = dto.getAuthKey();
                String authId = dubboUserService.getAuthIdByAuthKey(authKey);
                if (StringUtils.isBlank(authId)) {
                    throw new CommonException("登录失效,请从入口重新进入");

                }

                // 获取国泰用户
                UserGtXbExtEntity gtXbExtEntity = dubboUserService.getByUid(authId, merchantId);
                if (gtXbExtEntity != null) {
                    UserEntity user = dubboUserService.getById(gtXbExtEntity.getUserId());
                    if (user == null) {
                        throw new CommonException("gt用户信息不存在");
                    }
                    if (StringUtils.isBlank(gtXbExtEntity.getPhone())){
                        try {
                            // 通过手机号调用国泰接口，获取国泰用户信息
                            String body = gtHttpUtil.getCustomer(gtXbExtEntity.getUid(), phone);
                            JSONObject jsonObject = JSONUtil.parseObj(body);
                            Integer code = jsonObject.getInt("code");
                            if (null == code || code != 0){
                                throw new CommonException("请求国泰获取客户信息失败-"+jsonObject.getStr("message"));
                            }
                            JSONArray datas = jsonObject.getJSONArray("data");
                            JSONObject data = datas.getJSONObject(0);
                            Integer ifCust = data.getInt("ifCust");// 是否客户
                            if (null == ifCust || ifCust == 0){
                                // 非国泰客户
                            }
                            gtXbExtEntity.setCstId(data.getStr("customerNumber")); // 客户号
                            gtXbExtEntity.setName(data.getStr("customerName")); // 客户名
                            gtXbExtEntity.setBindServiceHall(data.getInt("ifBind")); // 是否绑定服务大厅
                            gtXbExtEntity.setVipFlag(data.getInt("isVIp")); // 是否vip
                            gtXbExtEntity.setVipLevelCode(data.getStr("vipLvl")); // vip等级
                            gtXbExtEntity.setPhone(phone);
                        }catch (Exception e){
                            // log.error("请求国泰接口异常", e);
                            throw new CommonException(ErrorEnum.error, e, "调用国泰客户查询接口异常");
                        }
                    }

                    dubboUserService.updGtxbUser(gtXbExtEntity);
                    if (StringUtils.isBlank(user.getPhone())){
                        user.setPhone(dto.getPhone());
                        dubboUserService.updateBaseInfo(user);
                    }
                }else {
                    throw new CommonException("gt用户信息不存在");
                }
            } else {
                throw new CommonException("暂不支持其他补全手机号方式");
            }
        }
    }


}
